package com.whfp.coky.ui.base

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.hjq.demo.action.ToastAction
import com.whfp.coky.action.ClickAction
import com.whfp.coky.action.HandlerAction
import com.whfp.coky.action.KeyboardAction
import com.whfp.coky.api.error.ErrorResult
import com.whfp.coky.event.EventMessage
import com.whfp.coky.utils.GenericParadigmUtil
import com.whfp.coky.utils.LogUtil
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe

/**
*
* onAttach：当Fragment与Activity发生关联时调用
* onCreate：创建Fragment时被回调，经历暂停或停止状态继而恢复后，想保留Fragment的基本组件，则在此进行初始化。
 * onCreateView：首次绘制页面时候调用，在此可以创建View，也可以返回null，这样不建议耗时操作。
 * onActivityCreated：Fragment绑定Activity，在onCreate方法已经执行完成并返回，在该方法内可以进行与Activity交互的UI操作，不能在此之前跟Activity进行交互。
 * onStart：启动 Fragment 时被回调，此时Fragment可见，只是还没有在前台显示，因此无法与用户进行交互
 * onResume：Fragment在前台可见，处于活动状态，用户可与之交互
 * onPause：Fragment处于暂停状态，但依然可见，用户不能与之交互
 * onStop：停止Fragment回调，Fragment完全不可见
 * onDestoryView：销毁与Fragment有关的视图，但未与Activity解除绑定
 * onDestory：销毁 Fragment 时被回调，通常按Back键退出或者Fragment被回收时调用此方法，此后接onDetach
 * onDetach：与onAttach相对应，当Fragment与Activity关联被取消时调用
 * setUserVisibleHint：调用此方法可以设置Fragment可见或者不可见。可以调用getUserVisibleHint()获得Fragment的可见或不可见状态，如果可见则进行懒加载操作
 *
 *
 * author coky
* created 2022/2/22 11:14
*/

abstract class BaseFragment<VM : BaseViewModel<VB>, VB : ViewBinding> : Fragment(),
    ToastAction, HandlerAction, KeyboardAction, ClickAction {

    /** Activity 对象 */
    private var activity: BaseActivity<*, *>? = null

    /** 当前是否加载过 */
    private var loading: Boolean = false

    /** 根布局 */
    private var contentView: View? = null

    lateinit var vModel: VM
    lateinit var vBinding : VB


//----------------------------------------lifecycle-----------------------------------------------
    /**
     * 获取绑定的act
     */
    @Suppress("UNCHECKED_CAST")
    override fun onAttach(context: Context) {
        super.onAttach(context)
        // 获得全局的 Activity
        activity = requireActivity() as BaseActivity<*, *>
    }

    /**
     * 界面绘制，不建议耗时
     */
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        if (null == contentView) {
            initVMVB(inflater,container)
            vModel.binding(vBinding)
            vModel.observe(this, this)

            contentView = vBinding.root
        }
        initView()
        LogUtil.e(getClassName())
        return contentView
    }

    /**
     * created，建立完成，可与act交互
     */
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initObserver()
    }

    /**
     * 初始化数据，耗时操作等。
     */
    override fun onResume() {
        super.onResume()
        Log.e("tag","loading...........................................${loading}")

        if (!loading) {
            loading = true
            initData()
            onFragmentResume(true)
            return
        }
        if (getAttachActivity()?.lifecycle?.currentState == Lifecycle.State.STARTED) {
            onActivityResume()
        } else {
            onFragmentResume(false)
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        contentView = null
    }

    override fun onDestroy() {
        super.onDestroy()
        EventBus.getDefault().unregister(this)
        loading = false
        removeCallbacks()
    }

    override fun onDetach() {
        super.onDetach()
        activity = null
    }

    /**
     * Fragment 可见回调
     *
     * @param first                 是否首次调用
     */
    protected open fun onFragmentResume(first: Boolean) {}

    /**
     * Activity 可见回调
     */
    protected open fun onActivityResume() {}

    private fun initObserver() {
        EventBus.getDefault().register(this)
        //loading
        vModel.isShowLoading.observe(viewLifecycleOwner, Observer {
            if (it) showDialog() else hideDialog()
        })
        //错误信息
        vModel.errorData.observe(viewLifecycleOwner, Observer {
            if (it.show) toast(it.errMsg)
            errorResult(it)
        })
    }

    abstract fun initView()
    abstract fun initData()


//----------------------------------------base function------------------------------------------
    /**
     * 获取绑定的 Activity，防止出现 getActivity 为空
     */
    open fun getAttachActivity(): BaseActivity<*, *>? {
        return activity
    }

    override fun getContext(): Context? {
        return activity
    }

    open fun getClassName(): String {
        val className = "BaseFragment"
        try {
            return javaClass.name
        } catch (e: Exception) {
        }
        return className
    }

    open fun initVMVB(inflater: LayoutInflater,
                      container: ViewGroup?){
        //初始化VM
        var pathfinders = ArrayList<GenericParadigmUtil.Pathfinder>()
        pathfinders.add(GenericParadigmUtil.Pathfinder(0, 0))
        val clazzVM = GenericParadigmUtil.parseGenericParadigm(javaClass, pathfinders) as Class<VM>
        vModel = ViewModelProvider(this).get(clazzVM)
        //初始化VB
        pathfinders = ArrayList()
        pathfinders.add(GenericParadigmUtil.Pathfinder(0, 1))
        val clazzVB = GenericParadigmUtil.parseGenericParadigm(javaClass, pathfinders)
        val method = clazzVB.getMethod("inflate", LayoutInflater::class.java)
        vBinding = method.invoke(null, layoutInflater,) as VB
    }

//----------------------------------------callback ----------------------------------------------
    //事件传递
    @Subscribe
    fun onEventMainThread(msg: EventMessage) {
        handleEvent(msg)
    }
    /**
     * 消息、事件接收回调
     */
    open fun handleEvent(msg: EventMessage) {}

    /**
     * 接口请求错误回调
     */
    open fun errorResult(errorResult: ErrorResult) {}


//----------------------------------------dialog--------------------------------------------------
    /**
     * 当前加载对话框是否在显示中
     */
    open fun isShowDialog(): Boolean {
        val activity : BaseActivity<*, *> =getAttachActivity()?: return false
        return activity.isShowDialog()
    }

    /**
     * 显示加载对话框
     */
    open fun showDialog() {
        getAttachActivity()?.showDialog()
    }

    /**
     * 隐藏加载对话框
     */
    open fun hideDialog() {
        getAttachActivity()?.hideDialog()
    }


//---------------------------------------other----------------------------------------------------
    /**
     * Fragment 按键事件派发
     */
    open fun dispatchKeyEvent(event: KeyEvent?): Boolean {
        val fragments: MutableList<Fragment?> = childFragmentManager.fragments
        for (fragment: Fragment? in fragments) {
            // 这个子 Fragment 必须是 BaseFragment 的子类，并且处于可见状态
            if (fragment !is BaseFragment<*,*> || fragment.getLifecycle().currentState != Lifecycle.State.RESUMED) {
                continue
            }
            // 将按键事件派发给子 Fragment 进行处理
            if (fragment.dispatchKeyEvent(event)) {
                // 如果子 Fragment 拦截了这个事件，那么就不交给父 Fragment 处理
                return true
            }
        }
        return when (event?.action) {
            KeyEvent.ACTION_DOWN -> onKeyDown(event.keyCode, event)
            KeyEvent.ACTION_UP -> onKeyUp(event.keyCode, event)
            else -> false
        }
    }

    /**
     * 按键按下事件回调
     */
    open fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        // 默认不拦截按键事件
        return false
    }

    /**
     * 按键抬起事件回调
     */
    open fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
        // 默认不拦截按键事件
        return false
    }

    override fun <V : View?> findViewById(id: Int): V? {
        return contentView?.findViewById<V>(id)
    }
}
